﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using XLua;
using Object = UnityEngine.Object;

namespace Al_FrameWork
{
    [Hotfix]
    [LuaCallCSharp]
    public class GlobalFunctions
    {
        /// <summary>
        /// 消息队列 queueLog
        /// </summary>
        private static Queue<string> queueLog = new Queue<string>();

        /// <summary>
        /// 获取最新日志
        /// </summary>开始比对资源
        /// <returns></returns>
        public static string GetLatestLog()
        {
            StringBuilder content = new StringBuilder();
            while (queueLog.Count != 0)
            {
                content = content.Append(queueLog.Dequeue() + "\n");
            }

            return content.ToString();
        }

        /// <summary>
        /// GetPersistentDataPath
        /// </summary>
        /// <param name="assetPath"></param>
        /// <returns></returns>
        public static string GetPersistentDataPath(string assetPath = null)
        {
            var outputPath = Path.Combine(Application.persistentDataPath);
            if (!string.IsNullOrEmpty(assetPath)) outputPath = Path.Combine(outputPath, assetPath);
#if UNITY_EDITOR && !UNITY_EDITOR_OSX
            return FormatToSysFilePath(outputPath);
#else
            return outputPath;
#endif
        }

        public static string CombineToUnityPath(string path1, string path2)
        {
            string path = string.Format("{0}/{1}", path1, path2);
            return path.Replace("\\", "/");
        }

        /// <summary>
        /// FormatToUnityPath
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string FormatToUnityPath(string path)
        {
            return path.Replace("\\", "/");
        }

        /// <summary>
        /// FormatToSysFilePath
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string FormatToSysFilePath(string path)
        {
            return path.Replace("/", "\\");
        }


        /// <summary>
        /// 大小显示
        /// </summary>
        /// <returns></returns>
        public static string FormatFileSize(long size)
        {
            if (size < 1024)
            {
                return string.Format("{0:0}B", size);
            }
            else if (size >= 1024 && size < 1024 * 1024)
            {
                return string.Format("{0:F2}KB", size / 1024);
            }
            else
            {
                return string.Format("{0:F2}MB", size / (1024 * 1024));
            }
        }

        /// <summary>   
        /// 重命名文件
        /// </summary>
        public static void ReNameFile(string sourcePath, string toPath)
        {
            if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(toPath)
                                                 || string.IsNullOrWhiteSpace(sourcePath) ||
                                                 string.IsNullOrWhiteSpace(toPath))
            {
                return;
            }

            try
            {
                File.Move(sourcePath, toPath);
                GlobalFunctions.LOG("改名成功:{0}=>{1}", sourcePath, toPath);
            }
            catch (Exception e)
            {
                GlobalFunctions.Err("重命名文件异常{0}", e.Message);
            }
        }

        /// <summary>
        /// 获取当前运行平台
        /// </summary>
        /// <returns></returns>
        public static string GetCurrentRunningPF()
        {
            string currentPlatform = "unKnown";
#if UNITY_STANDALONE_WIN || UNITY_EDITOR
            currentPlatform = "Windows";
#elif UNITY_IOS
        currentPlatform = "Ios";
#elif UNITY_ANDROID
        currentPlatform = "Android";
#endif
            return currentPlatform;
        }

        /// <summary>
        /// 获取当前运行平台
        /// </summary>
        /// <returns></returns>
        public static string GetRunningPF()
        {
            RuntimePlatform platform = Application.platform;

            switch (platform)
            {
                case RuntimePlatform.WindowsPlayer:
                case RuntimePlatform.WindowsEditor:
                    return "Windows";
                case RuntimePlatform.OSXPlayer:
                case RuntimePlatform.OSXEditor:
                case RuntimePlatform.IPhonePlayer:
                    return "Ios";
                case RuntimePlatform.Android:
                    return "Android";
                default:
                    return "unKnow";
            }
        }


        /// <summary>
        /// 彩色打印
        /// </summary>
        /// <param name="format"></param>
        /// <param name="color"></param>
        /// <param name="needShow">加重显示</param>
        /// <param name="message"></param>
        private static void ColorPrint(string format, string color, bool needShow, params object[] message)
        {
            for (int i = 0; i < message.Length; i++)
            {
#if UNITY_EDITOR || UNITY_EDITOR_WIN ||UNITY_STANDALONE_WIN
                if (needShow)
                {
                    message[i] = "<color=" + color + "><b>" + message[i] + "</b></color>";
                }
                else
                {
                    message[i] = "<color=" + color + ">" + message[i] + "</color>";
                }
#endif
            }

            string log = string.Format(format, message);
            if (GameConfig.isOpenLog)
            {
                if (queueLog.Count >= 200)
                {
                    queueLog.Dequeue();
                    queueLog.Enqueue(log);
                }
                else
                {
                    queueLog.Enqueue(log);
                }
            }
            else
            {
                UnityEngine.Debug.Log(log);
            }
        }

        /// <summary>
        /// 打印消息
        /// </summary>
        /// <param name="format"></param>
        /// <param name="message"></param>
        public static void LOG(string format, params object[] message)
        {
            ColorPrint(format, "#228B22", true, message);
        }

        /// <summary>
        /// lua打印
        /// </summary>
        /// <param name="format"></param>
        /// <param name="message"></param>
        public static void LUALOG(object message)
        {
            string log = "<color=#FF6347>LUA:</color>" + message;

            if (GameConfig.isOpenLog)
            {
                if (queueLog.Count >= 200)
                {
                    queueLog.Dequeue();
                    queueLog.Enqueue(log);
                }
                else
                {
                    queueLog.Enqueue(log);
                }
            }
            else
            {
                UnityEngine.Debug.Log(log);
            }
        }

        /// <summary>
        /// 打印错误消息
        /// </summary>
        /// <param name="format"></param>
        /// <param name="message"></param>
        public static void Err(string format, params object[] message)
        {
            ColorPrint(format, "#FF0000", true, message);
        }

        /// <summary>
        /// 创建单例
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="name"></param>
        /// <param name="isDontDestroy"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T GetInstance<T>(ref T instance, string name, bool isDontDestroy = true)
            where T : Object
        {
            if (instance != null) return instance;
            if (GameObject.FindObjectOfType<T>() != null)
            {
                instance = GameObject.FindObjectOfType<T>();
                return instance;
            }

            GameObject go = new GameObject(name, typeof(T));
            if (isDontDestroy) UnityEngine.Object.DontDestroyOnLoad(go);
            instance = go.GetComponent(typeof(T)) as T;
            return instance;
        }

        /// <summary>
        /// PackagePathToAssetsPath
        /// </summary>
        /// <param name="assetPath"></param>
        /// <returns></returns>
        public static string PackagePathToAssetsPath(string assetPath)
        {
            return "Assets/" + GameConfig.AssetBundlesFolderName + "/" + assetPath;
        }

        /// <summary>
        /// GetPersistentFilePath
        /// </summary>
        /// <param name="assetPath"></param>
        /// <returns></returns>
        public static string GetPersistentFilePath(string assetPath = null)
        {
            return "file://" + GetPersistentDataPath(assetPath);
        }

        /// <summary>
        /// CheckPersistentFileExsits
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static bool CheckPersistentFileExsits(string filePath)
        {
            var path = GetPersistentDataPath(filePath);
            return File.Exists(path);
        }

        /// <summary>
        /// GetAssetBundleFileUrl
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static string GetAssetBundleFileUrl(string filePath)
        {
            if (CheckPersistentFileExsits(filePath))
            {
                return GetPersistentFilePath(filePath);
            }
            else
            {
                return GetStreamingAssetsFilePath(filePath);
            }
        }

        /// <summary>
        /// GetStreamingAssetsFilePath
        /// </summary>
        /// <param name="assetPath"></param>
        /// <returns></returns>
        public static string GetStreamingAssetsFilePath(string assetPath = null)
        {
            string outputPath = "";
#if UNITY_EDITOR
            outputPath = Path.Combine("file://" + Application.streamingAssetsPath,
                GameConfig.AssetBundlesFolderName);
#else
            #if UNITY_IPHONE || UNITY_IOS
                        outputPath =
 Path.Combine("file://" + Application.streamingAssetsPath, GameConfig.AssetBundlesFolderName);
            #elif UNITY_ANDROID
                        outputPath = Path.Combine(Application.streamingAssetsPath, GameConfig.AssetBundlesFolderName);
            #else
                        Debug.LogError("Unsupported platform!!!");
            #endif
#endif
            if (!string.IsNullOrEmpty(assetPath))
            {
                outputPath = Path.Combine(outputPath, assetPath);
            }

            return outputPath;
        }


        /// <summary>
        /// AssetBundlePathToAssetBundleName
        /// </summary>
        /// <param name="assetPath"></param>
        /// <param name="assetBundleName"></param>
        /// <returns></returns>
        public static string AssetBundlePathToAssetBundleName(string assetPath, string assetBundleName = null)
        {
            if (!string.IsNullOrEmpty(assetPath))
            {
                if (assetPath.StartsWith("Assets/"))
                    assetPath = AssetsPathToPackagePath(assetPath);
                assetPath = assetPath.Replace(" ", "");
                assetPath = assetPath.Replace(".", "_");
                if (!string.IsNullOrEmpty(assetBundleName))
                    assetPath = assetPath.Substring(0,
                        assetPath.LastIndexOf(assetBundleName) + assetBundleName.Length);

                assetPath = assetPath + GameConfig.AssetBundleSuffix;
                return assetPath.ToLower();
            }

            return null;
        }

        /// <summary>
        /// AssetsPathToPackagePath
        /// </summary>
        /// <param name="assetPath"></param>
        /// <returns></returns>
        public static string AssetsPathToPackagePath(string assetPath)
        {
            var path = "Assets/" + GameConfig.AssetsFolderName + "/";
            if (assetPath.StartsWith(path))
            {
                return assetPath.Substring(path.Length);
            }

            GlobalFunctions.Err("Asset path is not a package path!");
            return assetPath;
        }


        /// <summary>
        /// CheckFileAndCreateDirWhenNeeded 校验路径是否存在 如果不存在创建
        /// </summary>
        /// <param name="filePath"></param>
        public static void CheckFileAndCreateDirWhenNeeded(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                return;
            }

            FileInfo file_info = new FileInfo(filePath);
            DirectoryInfo dir_info = file_info.Directory;
            if (!dir_info.Exists)
            {
                Directory.CreateDirectory(dir_info.FullName);
            }
        }

        /// <summary>
        /// SafeWriteAllBytes
        /// </summary>
        /// <param name="outFile"></param>
        /// <param name="outBytes"></param>
        /// <returns></returns>
        public static bool SafeWriteAllBytes(string outFile, byte[] outBytes)
        {
            try
            {
                if (string.IsNullOrEmpty(outFile))
                {
                    return false;
                }

                CheckFileAndCreateDirWhenNeeded(outFile);
                if (File.Exists(outFile))
                {
                    File.SetAttributes(outFile, FileAttributes.Normal);
                }
                LOG("outFile = {0}",outFile);
                File.WriteAllBytes(outFile, outBytes);
                return true;
            }
            catch (Exception e)
            {
                Err("SafeWriteAllBytes failed! path = {0} with err = {1}", outFile, e.Message);
                return false;
            }
        }
    }
}